// 为了防止ts的同目录文件变量重名报错问题，我们直接把代码写在一个自动执行函数里
(function () {
  // 定义一个动物类
  class Animal {
    name: string;
    age: number;

    constructor(name: string, age: number) {
      this.name = name;
      this.age = age;
    }

    sayHello() {
      console.log("动物再叫");
    }
  }

  /*
    class Dog extends Animal
        - 此时，Animal被称为父类，Dog被称为子类
        - 使用继承后，子类将会拥有父类的所有方法和属性
            这样只需要写一次即可让所有的子类都同时拥有父类中的属性与方法
            当然，如果希望在子类中添加一些父类中没有的属性或者方法直接加就好了
        - 如果在子类中添加了和父类同名的属性或者方法，那么子类的方法会覆盖掉父类的方法，不过要注意，不是去父类里覆盖，只是在子类自己这里改  
            这种子类覆盖掉父类的方法的形式，我们称为方法重写
  */

  // 定义一个狗类
  class Dog extends Animal {
    constructor(name: string, age: number) {
      super(name, age);
    }

    // sayHello是Animal类中就有的方法，你在这里又写了一个，那你写的这个就会覆盖掉Animal中的，成为Dog类实例专用的sayHello，这个叫做重写
    sayHello() {
      console.log("汪汪汪");
    }

    // Animal类中没有这个方法，你写在这里，那就是未来Dog类的实例独有的
    run() {
      console.log(`芜湖，我${this.name}起飞啦~`);
    }
  }

  const dog = new Dog("旺财", 2);
  dog.sayHello();

  //定义一个猫类
  class Cat extends Animal {
    constructor(name: string, age: number) {
      super(name, age);
    }

    sayHello() {
      console.log("喵呜~");
    }
  }

  const cat = new Cat("咪咪", 3);
  cat.sayHello();
})();
